package com.test19_多线程;

/**
 * 生产者与消费者模型
 */
public class Demo09_ProducerConsumer {

    public static void main(String[] args) {
        Message message = new Message();
        new Thread(new ProducerThread(message)).start();    // 启动生产者线程
        new Thread(new ConsumerThread(message)).start();    // 启动消费者线程
    }
}

/** 描述一个公共空间 */
class Message {
    private String title;   // 描述信息的标题
    private String content; // 描述信息的内容
    // flag = true：表示可以生产，但无法进行消费
    // flag = false：表示可以消费，但是无法生产
    private boolean flag = true;    // 设置一个标志位(红绿灯控制)

    public synchronized void set(String title, String content) throws InterruptedException {
        if (this.flag == false) {   // 不允许生产，只允许消费
            // 此时生产者线程暂停执行，等待消费者线程执行完毕后唤醒
            super.wait();
        }
        // 如果执行了如下的代码则表示允许进行生产，但是生产的最后需要唤醒等待的消费线程
        this.title = title;
        Thread.sleep(100);
        this.content = content;
        this.flag = false;  // 修改标志位，表示生产完成，可以消费
        super.notify();     // 唤醒其他等待线程
    }

    public synchronized String get() throws InterruptedException {
        if (this.flag == true) {    // 不允许消费，只允许生产
            // 此时消费者线程暂停执行，等待生产者线程执行完毕后唤醒
            super.wait();
        }
        // 如果执行了如下的代码则表示允许进行消费，但是消费的最后需要唤醒等待的生产线程
        Thread.sleep(50);
        this.flag = true;   // 修改标志位，表示消费完成，可以生产
        super.notify();     // 唤醒其他等待线程
        return "title = " + this.title + "、content = " + this.content;
    }
}

/** 生产者线程 */
class ProducerThread implements Runnable {
    private Message message;

    public ProducerThread(Message message) {
        this.message = message;
    }

    @Override
    public void run() {
        for (int x = 0; x < 50; x++) {  // 生产50次的信息
            try {
                if (x % 2 == 0) {
                    message.set("李兴华编程训练营", "yootk.ke.qq.com");
                } else {
                    message.set("沐言科技", "www.yootk.com");
                }
            } catch (Exception e) {}
        }
    }
}

/** 消费者线程 */
class ConsumerThread implements Runnable {
    private Message message;

    public ConsumerThread(Message message) {
        this.message = message;
    }

    @Override
    public void run() {
        for (int x = 0; x < 50; x++) {  // 获取50次的信息
            try {
                System.out.println("【消费者】" + this.message.get());
            } catch (Exception e) {}
        }
    }
}
